package com.sailing.xjpb.common;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.StreamReadConstraints;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.sailing.xjpb.common.exception.JsonException;
import com.sailing.xjpb.common.time.DateFormat;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.TimeZone;

/**
 * 基于springboot默认的json（com.fasterxml.jackson）组件的转换工具类
 *
 * @author YaoWei
 * createDate 2020年10月30日 上午10:22:39
 */
public class JsonUtils {

    private JsonUtils() {

    }

    /**
     * 默认时间格式化-可在序列化字段加上时间格式化注解覆盖该配置
     */
    private static final String DEFAULT_DATE_TIME_FORMAT = DateFormat.YYYY_MM_DD_HH_MM_SS;

    // 线程安全
    private static ObjectMapper objectMapper = null;

    private static final String CONVERT_ERROR_MESSAGE = "json转换java对象错误！";

    /**
     * Default setting for maximum string length: see StreamReadConstraints. Builder. maxStringLength(int) for details.
     */
    public static final int DEFAULT_MAX_STRING_LEN = 8_000_000;

    /**
     * 将对象转换为json字符串
     *
     * @param data java对象
     * @author YaoWei
     * createDate 2020年10月29日 下午6:27:17
     */
    public static String toJSONString(Object data) {
        try {
            return getObjectMapper().writeValueAsString(data);
        } catch (JsonProcessingException e) {
            throw new JsonException("json转换字符串过程中出现错误", e);
        }
    }

    /**
     * 将json字符串转化为map对象
     *
     * @param jsonData json字符串
     * @author YaoWei
     * createDate 2020年10月29日 下午6:35:07
     */
    public static ObjectNode parseObject(String jsonData) {
        return parseObject(jsonData, ObjectNode.class);
    }

    /**
     * 将json字符串转换为list对象
     *
     * @param <T>       list元素类型
     * @param arrayNode json对象
     * @param beanType  list元素类型
     * @author YaoWei
     * createDate 2020年10月29日 下午6:31:57
     */
    public static <T> T parseObject(JsonNode arrayNode, Class<T> beanType) {
        try {
            return getObjectMapper().convertValue(arrayNode, beanType);
        } catch (Exception e) {
            throw new JsonException(CONVERT_ERROR_MESSAGE, e);
        }
    }

    /**
     * 将json字符串转化为java对象
     *
     * @param jsonData json数据
     * @param beanType 对象中的object类型
     */
    public static <T> T parseObject(String jsonData, Class<T> beanType) {
        try {
            return getObjectMapper().readValue(jsonData, beanType);
        } catch (IOException e) {
            throw new JsonException(CONVERT_ERROR_MESSAGE, e);
        }
    }

    /**
     * 将json字符串转换为list对象
     *
     * @param <T>      list元素类型
     * @param jsonData json字符串
     * @param beanType list元素类型
     * @author YaoWei
     * createDate 2020年10月29日 下午6:31:57
     */
    public static <T> List<T> parseArray(String jsonData, Class<T> beanType) {
        try {
            JavaType javaType = getObjectMapper().getTypeFactory().constructParametricType(List.class, beanType);
            return getObjectMapper().readValue(jsonData, javaType);
        } catch (IOException e) {
            throw new JsonException(CONVERT_ERROR_MESSAGE, e);
        }
    }

    /**
     * 将json字符串转换为list对象
     *
     * @param <T>       list元素类型
     * @param arrayNode json对象
     * @param beanType  list元素类型
     * @author YaoWei
     * createDate 2020年10月29日 下午6:31:57
     */
    public static <T> List<T> parseArray(JsonNode arrayNode, Class<T> beanType) {
        try {
            JavaType javaType = getObjectMapper().getTypeFactory().constructParametricType(List.class, beanType);
            return getObjectMapper().convertValue(arrayNode, javaType);
        } catch (Exception e) {
            throw new JsonException(CONVERT_ERROR_MESSAGE, e);
        }
    }

    public static synchronized ObjectMapper getObjectMapper() {
        if (objectMapper == null) {
            objectMapper = new ObjectMapper();
            // 忽略 JSON 字符串中不识别的属性
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            // 指定时区
            objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
            // 日期类型字符串处理
            objectMapper.setDateFormat(new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT));
            StreamReadConstraints readConstraints =
                    StreamReadConstraints.builder().maxStringLength(DEFAULT_MAX_STRING_LEN).build();
            objectMapper.getFactory().setStreamReadConstraints(readConstraints);
        }
        return objectMapper;
    }

    public static synchronized void setObjectMapper(ObjectMapper objectMapper) {
        if (objectMapper != null) {
            JsonUtils.objectMapper = objectMapper;
        } else {
            getObjectMapper();
        }
    }
}
